home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / dosutil / mterm.c < prev    next >
C/C++ Source or Header  |  1994-03-20  |  17KB  |  679 lines

  1. /*
  2.  * MICRO-Terminal:
  3.  *
  4.  * This is a very simple communications program, which provides
  5.  * a subset ANSI (VT100) terminal emulation, and basic XMODEM
  6.  * (with checksum) file transfer.
  7.  *
  8.  * If HOTKEYS are specified on the command line, MTERM will install
  9.  * itself as a TSR (Ram-Resident) program, which can be invoked at
  10.  * any time by pressing the HOTKEYS. Available HOTKEYS are:
  11.  *        L - Left SHIFT
  12.  *        R - Right SHIFT
  13.  *        A - ALT
  14.  *        C - CONTROL
  15.  *        S - SysRq (Caution: some systems may not like this one)
  16.  *
  17.  *        EG: mterm LR    (Install with LEFT+RIGHT SHIFT for hotkeys)
  18.  *
  19.  * This demonstrates the use of the MICRO-C video interface
  20.  * and communications library functions for the IBM/PC, as well
  21.  * as the "SAVE_VIDEO", "RESTORE_VIDEO" and "TSR" functions.
  22.  *
  23.  * Copyright 1990-1994 Dave Dunfield
  24.  * All rights reserved.
  25.  *
  26.  * Permission granted for personal (non-commercial) use only.
  27.  *
  28.  * Compile command: cc mterm -fop
  29.  */
  30. #include <stdio.h>            /* Standard I/O definitions */
  31. #include <comm.h>            /* Comm     I/O definitions */
  32. #include <video.h>            /* Video    I/O definitions */
  33. #include <file.h>            /* File        I/O definitions */
  34. #include <tsr.h>            /* Tsr function definitions */
  35.  
  36. /* Screen output positions */
  37. #define    SETROW        3        /* Screen row for settings display */
  38. #define MSGROW        20        /* Screen row for messages */
  39. #define    MENROW        7        /* Screen row for menu items */
  40. #define    MAICOL        0        /* Screen column for main menu */
  41. #define    SUBCOL        20        /* Screen column for sub menu */
  42. #define    FILCOL        5        /* Screen column for file prompt */
  43. #define    FILSIZ        50        /* Maximum size of file name */
  44.  
  45. /* XMODEM parameters */
  46. #define BLOCK_SIZE    128        /* size of transmit blocks */
  47. #define RETRYS        10        /* maximum number of retrys */
  48. #define    SOH_TIMEOUT    5        /* How long to wait for start of packet */
  49. #define    RX_TIMEOUT    2        /* How long in wait for chars in packet */
  50. #define    ACK_TIMEOUT    5        /* How long to wait for acknowlege */
  51.  
  52. /* Line control codes */
  53. #define SOH            0x01    /* start of header */
  54. #define ACK            0x06    /* Acknowledge */
  55. #define NAK            0x15    /* Negative acknowledge */
  56. #define CAN            0x18    /* Cancel */
  57. #define EOT            0x04    /* end of text */
  58.  
  59. /* Menu text tables (Used by 'vmenu') */
  60.     char *main_menu[] = {
  61.         "Terminal Emulation",
  62.         "XMODEM Download",
  63.         "XMODEM Upload",
  64.         "Serial port config",
  65.         "Exit to DOS",
  66.         0 };
  67.  
  68.     char *setup_menu[] = {
  69.         "Comm port",
  70.         "Baudrate",
  71.         "Data bits",
  72.         "Parity",
  73.         "Stop bits",
  74.         "Xon/Xoff",
  75.         0 };
  76.  
  77. /* Uart configuration data tables */
  78. unsigned baudvalue[] =
  79.     { _110,  _300,  _1200,  _2400,  _4800,  _9600,  _19200,  _38400 };
  80. char *baudtext[] =
  81.     { "110", "300", "1200", "2400", "4800", "9600", "19200", "38400", 0 };
  82. char *databits[] = { "Five", "Six", "Seven", "Eight", 0 };
  83. char *parity[] = { "Odd", "Even", "Mark", "Space", "None", 0 };
  84. char *onetwo[] = { "One", "Two", 0 };
  85. char *onefour[] = { "One", "Two", "Three", "Four", 0 };
  86. char *flowctrl[] = { "Disabled", "Enabled", 0 };
  87.  
  88. /* Communications configuration parameters */
  89. int comm = 0, baud = 5, data = 3, par = 4, stop = 0, flow = 1;
  90.  
  91. /* Misc global variables */
  92. setup_selection = 0, transfer_selection = 0;
  93. char dfile[FILSIZ+1] = "", ufile[FILSIZ+1] = "";
  94.  
  95. /* Saved video screens, attributes & cursor position */
  96. char sav_buffer[(25*80)*2], sav_attr;
  97. int sav_xy;
  98. char video_save_area[SCR_BUF];
  99.  
  100. /*
  101.  * Main terminal program menu
  102.  */
  103. tty_main()
  104. {
  105.     int i;
  106.  
  107.     i = 0;            /* Default to top of menu */
  108.     save_video(video_save_area);
  109.  
  110. redraw:
  111.     draw_title();
  112.     vdraw_box(0, SETROW, 79, 2);
  113.     show_settings();
  114.  
  115.     for(;;) {
  116.         message("Select function and press ENTER");
  117.         if(vmenu(MAICOL, MENROW, main_menu, 0, &i))
  118.             continue;
  119.         switch(i) {
  120.             case 0 :        /* Terminal Emulation */
  121.                 if(!open_comm(flow))
  122.                     break;
  123.                 vcursor_line();
  124.                 restore_screen();
  125.                 ansi_term();
  126.                 save_screen();
  127.                 vcursor_off();
  128.                 goto redraw;
  129.             case 1 :        /* Download a file */
  130.                 if(open_comm(0))
  131.                     download(dfile);
  132.                 break;
  133.             case 2 :        /* Upload a file */
  134.                 if(open_comm(0))
  135.                     upload(dfile);
  136.                 break;
  137.             case 3 :        /* Setup serial port */
  138.                 setup();
  139.                 break;
  140.             case 4 :        /* Exit to DOS */
  141.                 Cclose();
  142.                 restore_video(video_save_area);
  143.                 return; } }
  144. }
  145.  
  146. /*
  147.  * Open a file for read or write (with overwrite prompt)
  148.  */
  149. HANDLE openf(fname, rw)
  150.     char *fname, rw;
  151. {
  152.     char c, omsg[80], *mode;
  153.     HANDLE fh;
  154.  
  155.     mode = "read";
  156.     fh = open(fname, F_READ);        /* First try and read the file */
  157.     if(rw) {                    /* If writing the file */
  158.         mode = "write";
  159.         if(fh) {
  160.             close(fh);
  161.             sprintf(omsg, "Overwrite existing %s (Y/N) ?", fname);
  162.             message(omsg);
  163.             do {
  164.                 c = toupper(vgetc());
  165.                 if((c == 0x1B) || (c == 'N'))
  166.                     return 0; }
  167.             while(c != 'Y'); }
  168.         fh = open(fname, F_WRITE); }
  169.     if(!fh) {
  170.         sprintf(omsg,"Cannot %s %s (Press ENTER)", mode, fname);
  171.         message(omsg);
  172.         while(vgetc() != '\n'); }
  173.     return fh;
  174. }
  175.  
  176. /*
  177.  * Open comm port with correct settings
  178.  */
  179. open_comm(flow)
  180.     char flow;
  181. {
  182.     int mode;
  183.  
  184.     /* Calculate the communications parameter value */
  185.     mode =    ((par << 4) & 0x30) |    /* parity type */
  186.             (data & 0x03) |            /* # data bits */
  187.             ((stop << 2) & 0x04) |    /* # stop bits */
  188.             ((par < 4) << 3);        /* parity enable */
  189.  
  190.     /* Open the communications port */
  191.     if(Copen(comm+1, baudvalue[baud], mode, SET_DTR|SET_RTS|OUTPUT_2)) {
  192.         message("Cannot open COM port (Press ENTER)");
  193.         while(vgetc() != '\n');
  194.         return 0; }
  195.  
  196.     /* Remove transparency if XON/XOFF flow control */
  197.     disable();
  198.     Cflags = (flow) ? Cflags & ~TRANSPARENT : Cflags | TRANSPARENT;
  199.     enable();
  200.  
  201.     return -1;
  202. }
  203.  
  204. /*
  205.  * Draw the title  header
  206.  */
  207. draw_title()
  208. {
  209.     vopen();
  210.     V_ATTR = REVERSE;
  211.     vdraw_box(0, 0, 79, 2);
  212.     vgotoxy(1, 1);
  213.     vputf("", 26);
  214.     vputf("MICRO-Terminal Version 1.3", 52);
  215.     V_ATTR = NORMAL;
  216.     vcursor_off();
  217. }
  218.  
  219. /*
  220.  * Draw the file transfer information box
  221.  */
  222. info_box(mode, filename)
  223.     char *mode, *filename;
  224. {
  225.     vdraw_box(SUBCOL, MENROW+1, 50, 8);
  226.     vgotoxy(SUBCOL+2, MENROW+3);
  227.     vprintf("%-19s: %s", mode, filename);
  228.     vgotoxy(SUBCOL+2, MENROW+5);
  229.     vputs("Blocks transferred : 0");
  230.     vgotoxy(SUBCOL+2, MENROW+7);
  231.     vputs("Transfer status    : ");
  232.     message("File transfer in progress (ESCAPE to abort)");
  233. }
  234.  
  235. /*
  236.  * Update the transfer status field
  237.  */
  238. transfer_status(text)
  239.     char *text
  240. {
  241.     vgotoxy(SUBCOL+23, MENROW+7);
  242.     vputf(text,10);
  243. }
  244.  
  245. /*
  246.  * Show the current COM port settings
  247.  */
  248. show_settings()
  249. {
  250.     vgotoxy(18, SETROW+1);
  251.     vprintf("COM%u: %5s,%2d,%5s,%2d  Xon/Xoff %-8s",
  252.         comm+1, baudtext[baud], data+5, parity[par], stop+1, flowctrl[flow]);
  253. }
  254.  
  255. /*
  256.  * Display a message
  257.  */
  258. message(ptr)
  259.     char *ptr;
  260. {
  261.     vgotoxy(0, MSGROW);
  262.     vcleos();
  263.     vmessage(38 - strlen(ptr)/2, MSGROW, ptr);
  264. }
  265.  
  266. /*
  267.  * Save the MICRO-TERMINAL video screen.
  268.  */
  269. save_screen()
  270. {
  271.     sav_xy = V_XY;
  272.     sav_attr = V_ATTR;
  273.     copy_seg(get_ds(), sav_buffer, V_BASE, 0, (25*80)*2);
  274. }
  275.  
  276. /*
  277.  * Restore the MICRO-TERMINAL video screen
  278.  */
  279. restore_screen()
  280. {
  281.     copy_seg(V_BASE, 0, get_ds(), sav_buffer, (25*80)*2);
  282.     V_ATTR = sav_attr;
  283.     V_XY = sav_xy;
  284.     vupdatexy();
  285. }
  286.  
  287. /*
  288.  * Comm port setup menu handler
  289.  */
  290. setup()
  291. {
  292.     message("Select setting (ESCAPE to cancel)");
  293.     for(;;) {
  294.         show_settings();
  295.         if(vmenu(SUBCOL, MENROW+1, setup_menu, 0, &setup_selection))
  296.             return;
  297.         switch(setup_selection) {
  298.             case 0 :    /* Comm port */
  299.                 vmenu(SUBCOL+11,MENROW+2,onefour,-1,&comm);
  300.                 break;
  301.             case 1 :    /* baudrate */
  302.                 vmenu(SUBCOL+11,MENROW+2,baudtext,-1,&baud);
  303.                 break;
  304.             case 2 :    /* Data bits */
  305.                 vmenu(SUBCOL+11,MENROW+2,databits,-1,&data);
  306.                 break;
  307.             case 3 :    /* Parity */
  308.                 vmenu(SUBCOL+11,MENROW+2,parity,-1,&par);
  309.                 break;
  310.             case 4 :    /* Stop bits */
  311.                 vmenu(SUBCOL+11,MENROW+2,onetwo,-1,&stop);
  312.                 break;
  313.             case 5 :    /* Flow control */
  314.                 vmenu(SUBCOL+11,MENROW+2,flowctrl,-1,&flow); } }
  315. }
  316.  
  317. /*
  318.  * Terminal mode using ANSI (VT100) emulation
  319.  */
  320. ansi_term()
  321. {
  322.     char c, xy_flag, *ptr;
  323.     unsigned x, y, state, value, parm, parms[5];
  324.  
  325.     /* ANSI (VT100) Function key translation table */
  326.     static char *ansi_keys[] = {
  327.         "\x1B[A", "\x1B[B", "\x1B[D",